#include <os_common_api.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <bt_manager.h>
//#include "btmusic.h"
#include "uart_control.h"
#include "app_defines.h"
#include "input_manager.h"
#include "app_manager.h"
#include "app_switch.h"
#include "volume_manager.h"
#include "audio_system.h"
#include "sys_manager.h"





static struct uart_buf_info uart_buf[UART_BUF_QUEUED];
struct uart_data_format send_cache;			/* 串口TX临时缓存区 */

u8_t rx_data[2][UART_MTU];
u8_t rx_index[2]={0};

u8_t alarm_ringing_enable;
u8_t mcu_is_ready=0;
struct uart_msg_info remote_dev_info;

static K_FIFO_DEFINE(cmds_queue_uart1);
static K_FIFO_DEFINE(avail_queue_uart1);
static os_delayed_work uart1_control_run_delaywork;
extern void system_stop_sync(void);
extern void system_sync_to_remote_start(u8_t sync_mode);
extern u8_t system_get_mic_status(void);



/**
 * uart1 tx send
 *
 * @param
 *  p_data
 */
void uart1_send_to_apt(     u8_t *p_data,u8_t writen_len)
{
    //SYS_LOG_INF(" reply3 %d\n", writen_len);
    if(writen_len > UART_MTU){
        SYS_LOG_ERR("uart1: TX data_len err.");
        return;
    }
    if(writen_len ==0){
        SYS_LOG_ERR("uart1: TX cmd_len err.");
        return;
    }
	printk("TX:\n");
    print_buffer(p_data, 1, writen_len, 16, 0);
    uart_pipe_send((u8_t *)p_data, writen_len);
}

void get_cur_status(void)
{
	if(strcmp(app_manager_get_current_app(), APP_ID_BTMUSIC)==0)
	{
		u16_t bt_state;
		bt_state=bt_manager_get_status()&BT_STATUS_PLAYING;
	}
	else if(strcmp(app_manager_get_current_app(), APP_ID_LINEIN)==0)
	{
		
	}
}
//len+cmd+param
u8_t get_checksum(u8_t *data,u8_t length)
{
	u16_t checksum=0,i=0;
	for(i=0;i<length;i++)
	{
		checksum+=data[i];
	}
	checksum=0xFF-(checksum&0xFF);
	printf("cur checksum:0x%x\n",checksum);
	return checksum;
}
#define HEAD_OFFSET 0
#define LEN_OFFSET 1
#define CMD_OFFSET 2
#define PARAM_OFFSET 3
#define CHECKSUM_OFFSET 4
#define END_OFFSET 5

void report_msg_to_main(uint8_t msg_cmd,u8_t msg_data)
{
	struct app_msg  msg = {0};
	msg.type = msg_cmd;
	msg.content[0]=msg_data;
	send_async_msg("main", &msg);
}



/**
 * uart1 rx recv dispatch
 *
 * @param
 *  p_data
 */
u8_t g_bat_status = 1;
u8_t g_mcu_reset = 0;
u8_t data_buf[32];
void uart1_dispatch(     u8_t *p_data)
{
	struct uart_data_format *p_reply = (void *)p_data;
	u16_t writen_len = p_reply->data_len;
    //u8_t cmd = p_reply->cmd;

    //todo send event/msg base rx info
#if 0//def UART_DEBUG
    SYS_LOG_INF(" magic %x\n", p_reply->magic);

	//write output
    p_reply->magic = 0x3E;  //应答flag ">"

    SYS_LOG_INF(" reply %d,%x\n", writen_len, p_data[writen_len]);
    //追加/替换最后一个字符为"@"来做ack
    if(writen_len < UART_MTU)
    {
        p_data[writen_len] = 0x40;
        SYS_LOG_INF(" data %x,%x\n", p_data[writen_len-1], p_data[writen_len]);
        uart_pipe_send((u8_t *)p_reply, writen_len+1);
    }
    else
    {
        p_data[UART_MTU-1] = 0x40;
        uart_pipe_send((u8_t *)p_reply, UART_MTU);
    }
    print_buffer(p_data, 1, writen_len+1, 16, 0);
#else
	if(p_reply->magic!=MAGIC_HEAD)
	{
		SYS_LOG_INF(" magic head err:%x\n",p_reply->magic);
		return ;
	}
	if(p_reply->end!=MAGIC_END)
	{
		SYS_LOG_INF(" magic end err:%x\n",p_reply->end);
		return ;
	}
	if(p_reply->ack==ACK_NO)
	{
		system_stop_sync();
		memcpy(&remote_dev_info,&p_reply->msg_info,sizeof(struct uart_msg_info));
		return;
	}
	else if(p_reply->ack==ACK_OUT)
	{		
		if(writen_len!=0)
		{	
			u8_t msg_type,msg_data=0;
		    SYS_LOG_INF("deal rx msg!!!\n");
			k_sleep(4);
			system_sync_to_remote_start(ACK_NO);
			switch(p_reply->cmd)
			{
				case CMD_SYNC_ALL:
					memcpy(&remote_dev_info,&p_reply->msg_info,sizeof(struct uart_msg_info));
					if(p_reply->msg_info.mute!=system_get_mic_status())
					{
						if(p_reply->msg_info.mute)
						{
							msg_type=MSG_MUTE_EN_EVENT;
						}
						else
						{
							msg_type=MSG_MUTE_DIS_EVENT;
						}
						report_msg_to_main(msg_type,msg_data);
					}
					
					break;
				case CMD_SYNC_MUTE:
					if(p_reply->data[0])
					{
						msg_type=MSG_MUTE_EN_EVENT;
					}
					else
					{
						msg_type=MSG_MUTE_DIS_EVENT;
					}
					report_msg_to_main(msg_type,msg_data);
					break;
				case CMD_SYNC_VOLUME:
					msg_data=p_reply->data[0];
					msg_type=MSG_SYNC_VOL_EVENT;
					report_msg_to_main(msg_type,msg_data);
					break;
				case CMD_SYNC_MODE:
					msg_data=p_reply->data[0];
					break;
				case CMD_SYNC_BT_STATUS:
					msg_data=p_reply->data[0];
					break;
				case CMD_SYNC_USB_STATUS:
					msg_data=p_reply->data[0];
					break;
				default:
					return;
			}
			
			
		}
	}
   
#endif	
	return;
}
/**
 * exec in system workqueue
 */
static void uart1_cmd_handle(os_work *work)
{
	struct uart_buf_info *cmd_buf = NULL;
	#if 1
	u8_t i;
	for(i=0;i<UART_BUF_QUEUED;i++)
	{
		cmd_buf = k_fifo_get(&cmds_queue_uart1, K_NO_WAIT);

	    //SYS_LOG_INF(" %08x\n", (unsigned)cmd_buf);
		if (cmd_buf == NULL)
	    {
	        continue;
	    }
	    SYS_LOG_INF(" %08x\n", (unsigned)cmd_buf->data);

		//dispatch handle
	    uart1_dispatch(cmd_buf->data);
		k_fifo_put(&avail_queue_uart1, cmd_buf);
	}
	#else
	cmd_buf = k_fifo_get(&cmds_queue_uart1, K_NO_WAIT);

    //SYS_LOG_INF(" %08x\n", (unsigned)cmd_buf);
	if (cmd_buf == NULL)
    {
        SYS_LOG_ERR("uart1: cmd_buf get error 3");
		return;
    }
    //SYS_LOG_INF(" %08x\n", (unsigned)cmd_buf->data);
	//dump
	//print_buffer(cmd_buf->data, 1, cmd_buf->data_info.data_len+1, 16, 0);
	//print_buffer(cmd_buf->data, 1, cmd_buf->data_info.data_len, 16, 0);

	//dispatch handle
    uart1_dispatch(cmd_buf->data);

	k_fifo_put(&avail_queue_uart1, cmd_buf);
	#endif
}

/**
 * notice this function exec in ISR context
 */
static u8_t *uart1_recv_cb(u8_t *buf, size_t *off)
{
    struct uart_data_format *cmds_buf = (void *) buf;
    struct uart_buf_info *new_buf;
    u16_t len;
	//printk("buf addr:0x%x\n",(unsigned)buf);
	printk("RX:\n");
	//print_buffer(buf, 1, *off, 16, (u32_t)*buf);
    //SYS_LOG_INF("1> %08x, %ld,%ld\n", (unsigned)buf, *off, sizeof(*cmds_buf));
    print_buffer(buf, 1, *off, 16, 0);
    if (cmds_buf->magic != MAGIC_HEAD) {
        SYS_LOG_ERR("uart1: RX magic error 0x%x,len:%ld", cmds_buf->magic,*off);
        //if(*off >= UART_MTU)
            *off = 0;
        return buf;
    }
#if 0
    if (*off < sizeof(*cmds_buf)) {
        SYS_LOG_ERR("uart1: RX data not enough 0");
        if(*off >= UART_MTU)
            *off = 0;
		return buf;
	}
#else
    //uart control的最小长度，防止拿到错误的数据长度
    if(*off < 0x03){
        //SYS_LOG_ERR("uart1: RX data not enough 0");
        if(*off >= UART_MTU)
            *off = 0;
        return buf;
    }
#endif
    //SYS_LOG_INF("2> %08x, %d,%ld\n", (unsigned)buf, cmds_buf->data_len, *off);

    len = cmds_buf->data_len;

    //防止buffer长度溢出，规避死循环
    if(len > UART_MTU){
        *off = 0;
        SYS_LOG_ERR("uart1: TX data_len err %d", len);
        return buf;
    }

    //判断输入长度是否达到格式要求，未达到则重新缓存
    if (*off < len) {
        //SYS_LOG_ERR("uart1: RX data not enough 1:%ld", *off);
        if(*off <= UART_MTU)    //防止超出buffer大小
        {
            return buf;
        }
        SYS_LOG_ERR("uart1: RX buf full");
    }

	#if 1
    new_buf =  k_fifo_get(&avail_queue_uart1, K_NO_WAIT);
    if (!new_buf) {
        SYS_LOG_ERR("uart1: RX overflow 2");
        *off = 0;
        return buf;
    }
	#endif
    k_fifo_put(&cmds_queue_uart1, CONTAINER_OF(buf, struct uart_buf_info, data));
    os_delayed_work_submit(&uart1_control_run_delaywork, UART_RXTX_INTERVAL);
	
    *off = 0;
	memset(new_buf->data, 0, UART_MTU);
    return new_buf->data;
}


/*initialize uart1*/
void uart1_setting_init(void)
{
	int i;
	struct uart_buf_info *buf;

	for (i = 0; i < UART_BUF_QUEUED; i++) {
		k_fifo_put(&avail_queue_uart1, &uart_buf[i]);
	}

	buf = k_fifo_get(&avail_queue_uart1, K_NO_WAIT);
	uart_pipe_register(buf->data, UART_MTU, uart1_recv_cb);

	SYS_LOG_INF("uart1 communication init\n");
	os_delayed_work_init(&uart1_control_run_delaywork, uart1_cmd_handle);
}

